/**
 * Create by mzq
 * Description: 连接蓝牙操作
 * Date: 2025/2/14 09:11
 * Update: 2025/2/14 09:11
 */

import { ab2hex, setMTu, writeBLEState } from './BluetoothFun'
import { toast } from '@/utils'
import store from '@/store'

/**
 * 初始化蓝牙适配器
 * 打开蓝牙适配器，并获取蓝牙适配器状态
 * @param {Boolean} autoSearch - 是否自动搜索设备，默认为true
 * @returns {Promise} 返回Promise对象，连接成功时resolve，失败时reject
 */
export const handleConnect = (autoSearch = true) => {
  return new Promise((resolve, reject) => {
    uni.openBluetoothAdapter({
      success: (res) => {
        console.log('蓝牙初始化成功')
        if (autoSearch) {
          getBluetoothAdapterState()
            .then(() => resolve())
            .catch((err) => reject(err))
        } else {
          console.log('蓝牙已初始化，但不自动搜索设备')
          resolve()
        }
      },
      fail: (err) => {
        console.log('蓝牙初始化失败：', err)
        uni.showToast({
          title: '请打开蓝牙',
          icon: 'none',
        })
        reject(err)
      },
    })
  })
}

/**
 * 获取蓝牙适配器状态
 * 检查蓝牙适配器是否可用，如果可用则开始搜索蓝牙设备
 * @returns {Promise} 返回Promise对象，获取状态成功时resolve，失败时reject
 */
const getBluetoothAdapterState = () => {
  return new Promise((resolve, reject) => {
    uni.getBluetoothAdapterState({
      success: (res) => {
        console.log('蓝牙适配器状态：', res)
        if (res.available) {
          startBluetoothDevicesDiscovery()
            .then(() => resolve())
            .catch((err) => reject(err))
        }
      },
      fail: (err) => {
        console.log('获取蓝牙适配器状态失败：', err)
        uni.showToast({
          title: '获取蓝牙状态失败',
          icon: 'none',
        })
        reject(err)
      },
    })
  })
}

/**
 * 搜索蓝牙设备
 * 开始搜索周围的蓝牙设备，并在2秒后停止搜索
 * @returns {Promise} 返回Promise对象，搜索成功时resolve，失败时reject
 */
const startBluetoothDevicesDiscovery = () => {
  return new Promise((resolve, reject) => {
    let arr = []
    uni.startBluetoothDevicesDiscovery({
      allowDuplicatesKey: false, // 不允许重复上报同一设备
      interval: 0, // 搜索间隔为0，尽可能快地搜索
      success: (res) => {
        uni.onBluetoothDeviceFound((devices) => {
          uni.getBluetoothDevices({
            success: (res) => {
              console.log('设备列表：', res)
              arr = res.devices
            },
          })
        })

        // 2秒后停止搜索
        setTimeout(() => {
          stopBluetoothDevicesDiscovery(arr)
            .then(() => resolve())
            .catch((err) => reject(err))
        }, 2000)
      },
      fail: (err) => {
        console.log('搜索蓝牙设备失败：', err)
        uni.showToast({
          title: '搜索设备失败',
          icon: 'none',
        })
        reject(err)
      },
    })
  })
}

/**
 * 停止搜索蓝牙设备
 * 停止搜索并筛选出目标设备（EI-B100），如果找到则建立连接
 * @param {Array} arr - 搜索到的蓝牙设备列表
 * @returns {Promise} 返回Promise对象，停止搜索成功时resolve，失败时reject
 */
const stopBluetoothDevicesDiscovery = (arr) => {
  return new Promise((resolve, reject) => {
    uni.stopBluetoothDevicesDiscovery({
      success: (res) => {
        // B100_8bc08716e7dcfa2
        let searchDeviceName = 'EI-B100' // 目标设备名称
        console.log('停止搜索蓝牙设备成功')
        let DevicesArr = []

        if (arr.length !== 0) {
          // 筛选出名称包含EI-B100的设备
          for (let i = 0; i < arr.length; i++) {
            if (arr[i].name.indexOf(searchDeviceName) !== -1) {
              console.log('搜索到的设备是', arr[i])
              DevicesArr.push(arr[i])
            }
          }

          // 根据找到的设备数量进行不同处理
          if (DevicesArr.length >= 2) {
            toast('发现了多个设备')
            resolve(true) // 返回true表示找到了设备(多个)
          }
          if (DevicesArr.length === 0) {
            // 改为reject，以便触发catch分支
            reject(new Error('未找到设备')) 
          }
          if (DevicesArr.length === 1) {
            console.log('DevicesArr[0]', DevicesArr[0])
            createBLEConnection(DevicesArr[0]) // 建立蓝牙连接
            resolve(true) // 返回true表示找到了设备
          }
          console.log('DevicesArr', DevicesArr)
        }else{
          // 改为reject，以便触发catch分支
          reject(new Error('未找到设备'))
        }
      },
      fail: (err) => {
        console.log('停止搜索蓝牙设备失败')
        reject(err)
      },
    })
  })
}

/**
 * 建立蓝牙连接
 * 与指定的蓝牙设备建立连接，并获取设备服务
 * @param {Object} device - 蓝牙设备对象，包含deviceId等信息
 */
const createBLEConnection = (device) => {
  const deviceId = device.deviceId
  uni.createBLEConnection({
    deviceId,
    success: (res) => {
      console.log('connected success', res)
      getBLEDeviceServices(deviceId) // 获取设备服务
    },
  })

  // 监听蓝牙连接状态
  listenBLEConnectionStateChange()
}

/**
 * 监听蓝牙连接状态变化
 * 监听蓝牙连接状态变化事件，并更新store中的连接状态
 */
const listenBLEConnectionStateChange = () => {
  uni.onBLEConnectionStateChange((res) => {
    console.log(
      `device ${res.deviceId} state has changed, connected: ${res.connected}`
    )

    // 更新store中的蓝牙设备ID和连接状态
    store.commit('setBleId', res.deviceId)
    store.commit('setIsConnected', res.connected)
  })
}

/**
 * 获取蓝牙服务
 * 设置MTU并获取设备的服务列表，找到目标服务后开启数据监听
 * @param {String} deviceId - 蓝牙设备ID
 */
const getBLEDeviceServices = (deviceId) => {
  // 设置MTU（最大传输单元）
  setTimeout(() => {
    setMTu(deviceId)
  }, 500)

  // 延迟2秒获取服务，确保MTU设置完成
  setTimeout(async () => {
    uni.getBLEDeviceServices({
      deviceId,
      success: (res) => {
        res.services.forEach((service) => {
          // 查找目标服务（FFE0服务）
          if (service.uuid.indexOf('FFE0') !== -1) {
            // 在此处开启数据监听 （接收）
            uni.onBLECharacteristicValueChange((res) => {
              store.dispatch('asyncOriginalData', res.value) // 将接收到的数据存入store
              console.log('监听到的蓝牙数据000>>>>>', res.value)
              console.log('ab2', ab2hex(res.value)) // 转换为十六进制显示
            })
            getBLEDeviceCharacteristics(deviceId, service.uuid) // 获取服务的特征值
          }
        })
      },
    })
  }, 2000)
}

/**
 * 获取蓝牙设备特征值
 * 获取指定服务的特征值，并根据特征值的属性进行相应操作
 * @param {String} deviceId - 蓝牙设备ID
 * @param {String} serviceId - 服务UUID
 */
const getBLEDeviceCharacteristics = (deviceId, serviceId) => {
  console.log('获取蓝牙特征值1', serviceId)
  uni.getBLEDeviceCharacteristics({
    deviceId: deviceId,
    serviceId: serviceId,
    success: (res) => {
      console.log('getBLEDeviceCharacteristics success', res)
      res.characteristics.forEach((characteristic) => {
        // 如果特征值支持读操作
        if (characteristic.properties.read) {
          uni.readBLECharacteristicValue({
            characteristicId: characteristic.uuid,
            deviceId,
            serviceId,
          })
        }

        // 如果特征值支持notify或indicate操作
        if (
          characteristic.properties.notify ||
          characteristic.properties.indicate
        ) {
          uni.notifyBLECharacteristicValueChange({
            state: true, // 启用notify
            deviceId,
            serviceId,
            characteristicId: characteristic.uuid,
            success(res) {
              // console.log('notifyBLECharacteristicValueChange success', res);
              // setTimeout(() =>{
              //   setMTu(deviceId)
              // },1000)
            },
          })
        }

        // 如果特征值支持写操作
        if (characteristic.properties.write) {
          // 将设备信息保存到store
          store.commit('setDeviceId', deviceId)
          store.commit('setServiceId', serviceId)
          store.commit('setCharacteristicId', characteristic.uuid)
          // 延迟800ms后获取电量信息
          setTimeout(() => {
            writeBLEState(10) // 发送获取电量的指令
          }, 800)
        }
      })
    },
  })
}
